package top.whysu.edevice.service.system.impl;

import cn.hutool.crypto.digest.DigestUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import top.whysu.edevice.constant.CodeConstant;
import top.whysu.edevice.constant.Constant;
import top.whysu.edevice.constant.DataDictionary;
import top.whysu.edevice.dto.system.AccountDTO;
import top.whysu.edevice.dto.system.LoginResponseDTO;
import top.whysu.edevice.dto.system.WriteProperty;
import top.whysu.edevice.exception.BusinessException;
import top.whysu.edevice.global.ThreadPoolBuilder;
import top.whysu.edevice.po.system.AccountPO;
import top.whysu.edevice.service.system.AccountService;
import top.whysu.edevice.service.system.LoginService;
import top.whysu.edevice.utils.CommonUtil;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.Date;

/**
 * 登录业务实现类
 */
@Service
public class LoginServiceImpl implements LoginService {

    private static final Logger LOGGER = LoggerFactory.getLogger(LoginServiceImpl.class);

    @Resource
    private AccountService accountService;
    @Resource
    private ThreadPoolBuilder threadPoolBuilder;

    @Override
    public LoginResponseDTO login(AccountDTO accountDTO) throws BusinessException {
        LoginResponseDTO loginResponseDTO = new LoginResponseDTO();
        Subject subject = SecurityUtils.getSubject();

        // 获取服务器ip地址
        WriteProperty writeProperty = CommonUtil.getNetWorkInfo();
        if (writeProperty != null && StringUtils.isNotBlank(writeProperty.getLocalIp())) {
            loginResponseDTO.setWebsocketIp(writeProperty.getLocalIp());
        } else {
            loginResponseDTO.setWebsocketIp("127.0.0.1");
        }
        String username = accountDTO.getUsername();
        String password = accountDTO.getPassword();
        // 非空校验
        if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
            throw new BusinessException(CodeConstant.Http.ERROR_PWD_OR_USERNAME, "账号或密码不能为空");
        }
        //已登陆则跳到首页
        if (subject.isAuthenticated()) {
            loginResponseDTO.setToken(subject.getSession().getId().toString());
        }
        // 重新加密明文密码用于校验
        try {
            password = DigestUtil.sha256Hex(password);
        } catch (Exception e) {
            LOGGER.error("用户登录密码加密异常", e);
            throw new BusinessException(CodeConstant.Http.INFO_ERROR, "密码加密异常");
        }
        // 根据账号查询用户信息
        AccountPO authUserInfo = accountService.selectByUsername(username);
        if (authUserInfo == null || !username.equals(authUserInfo.getUsername())) {
            // 如果未存在则返回失败
            throw new BusinessException(CodeConstant.Http.ERROR_PWD_OR_USERNAME, "账号不存在");
        } else {
            // 如果是注销状态则返回失败
            if (authUserInfo.getAccountState() != null &&
                    DataDictionary.AccountState.DELETE.equals(authUserInfo.getAccountState().toString())) {
                throw new BusinessException(CodeConstant.Http.USER_STOP_USE, "用户已注销");
            }
        }
        // 登录
        Serializable sessionId;
        try {
            subject.login(new UsernamePasswordToken(username, password));
            sessionId = subject.getSession().getId();
        } catch (AuthenticationException e) {
            LOGGER.error("账号或密码错误", e);
            throw new BusinessException(CodeConstant.Http.ERROR_PWD_OR_USERNAME, "账号或密码错误");
        }
        // 更新最后一次登录时间
        try {
            authUserInfo.setLastLoginTime(new Date());
            accountService.updateAccountLastLoginTime(authUserInfo);
        } catch (Exception e) {
            LOGGER.error("更新登录时间异常", e);
            throw new BusinessException(CodeConstant.Http.EXECUTE_FAIL, "更新登录时间异常");
        }
        // 都没异常则返回成功
        loginResponseDTO.setToken(sessionId.toString());
        return loginResponseDTO;
    }

    /**
     * 退出登录
     */
    @Override
    public void logout() {
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
    }

    @Override
    public Boolean isFirstLogin() {
        // 获取当前登录用户
        String currentAccount = (String) SecurityUtils.getSubject().getPrincipal();
        AccountPO accountPO = accountService.selectByUsername(currentAccount);
        // 最后登录时间为空并且密码为默认密码时为第一次登录
        boolean result;
        try {
            result = null == accountPO.getLastLoginTime() || DigestUtil.sha256Hex(Constant.PASSWORD.DEFAULT).equals(accountPO.getPassword());
        } catch (Exception e) {
            throw new BusinessException(CodeConstant.Http.EXECUTE_FAIL, "加密密码时出现异常！");
        }
        return result;
    }


    public static void main(String[] args) {
        System.out.println(DigestUtil.sha256Hex("123456"));
    }
}
